
//{{{ file documentation -------------------------------------------------------

/*!
 * @file  mainwindow.cpp
 * @brief dicodor mainwindow class implémentation
 */

//}}} --------------------------------------------------------------------------
//{{{ includes / predeclarations -----------------------------------------------

#include "mainwindow.h"
#include "about.h"
//#include "moc_mainwindow.cpp"	moc V5 sera incompatible V4

#include "messages.h"
#include "ui_mainwindow.h"

#include <QtGui/QDesktopWidget>
#include <QtGui/QFileDialog>
#include <QtGui/QTextDocumentWriter>
#include <QtGui/QProgressBar>
#include <QtGui/QFontDatabase>
#include <QtGui/QFontDialog>
#include <QtGui/QPrintDialog>
#include <QtGui/QPrinter>
#include <QtGui/QToolButton>

//}}} --------------------------------------------------------------------------
//{{{ MainWindow ---------------------------------------------------------------
//}}} --------------------------------------------------------------------------
//{{{ .MainWindow (const QString & documentPath, QWidget * parent) ------------

MainWindow::MainWindow (const QString & documentPath, QWidget * parent) :
	QMainWindow (parent) ,
	ui (new Ui::MainWindow) ,
	m_config (new Config (this)) ,
	m_documentPath (documentPath)
{

	ui->setupUi (this) ;

	m_messages.clear();

	initTests ();
	initWindow ();
	initMenu ();
	initToolbar ();
	initDocument ();
	initConnect ();

	if (m_edit->open (documentPath))
	{
		setWindowTitle (QString ("%1[*] - Dicodor").arg (documentPath)) ;
		setWindowFilePath (documentPath) ;
		setWindowModified (false) ;
	}
}

//}}} --------------------------------------------------------------------------
//{{{ .~MainWindow() -----------------------------------------------------------

MainWindow::~MainWindow()
{
	delete ui;
}

//}}} --------------------------------------------------------------------------
//{{{ .void initTests() -----------------------------------------------------

void MainWindow::initTests()
{
}

//}}} --------------------------------------------------------------------------
//{{{ .void initWindow() ----------------------------------------------------

void MainWindow::initWindow ()
{
	// centrage sur l'écran
	const QDesktopWidget dw;
	const QRect& screen (dw.availableGeometry());
	setGeometry(
				screen.center ().x () - width () / 2,
				screen.center ().y () - height () / 2,
				width (),
				height ()) ;

	//	setWindowTitle (tr ("(sans nom)[*] - Dicodor")) ;
	setWindowIcon (Config::appIcon()) ;

	m_progressDialog = new QProgressDialog (tr ("Analyse en cours..."),
											tr ("Interrompre"),
											0,
											0,
											this);

	m_progressDialog->setMinimumDuration (2000);

	QProgressBar* bar = new QProgressBar (m_progressDialog);
	bar->setOrientation (Qt::Horizontal);
	bar->setAlignment (Qt::AlignCenter);
	bar->setFormat (tr ("Avancement : %v/%m"));
	m_progressDialog->setBar (bar);

}

//}}} --------------------------------------------------------------------------
//{{{ .void initMenu() ------------------------------------------------------

//{{{ style constants ----------------------------------------------------------

/*
 * Constant         Value Description
 * QStyle::SP_TitleBarMinButton     1 Minimize button on title bars (e.g., in QMdiSubWindow).
 * QStyle::SP_TitleBarMenuButton    0 Menu button on a title bar.
 * QStyle::SP_TitleBarMaxButton     2 Maximize button on title bars.
 * QStyle::SP_TitleBarCloseButton    3 Close button on title bars.
 * QStyle::SP_TitleBarNormalButton    4 Normal (restore) button on title bars.
 * QStyle::SP_TitleBarShadeButton    5 Shade button on title bars.
 * QStyle::SP_TitleBarUnshadeButton    6 Unshade button on title bars.
 * QStyle::SP_TitleBarContextHelpButton   7 The Context help button on title bars.
 * QStyle::SP_MessageBoxInformation    9 The "information" icon.
 * QStyle::SP_MessageBoxWarning    10 The "warning" icon.
 * QStyle::SP_MessageBoxCritical    11 The "critical" icon.
 * QStyle::SP_MessageBoxQuestion    12 The "question" icon.
 * QStyle::SP_DesktopIcon      13 The "desktop" icon.
 * QStyle::SP_TrashIcon      14 The "trash" icon.
 * QStyle::SP_ComputerIcon      15 The "My computer" icon.
 * QStyle::SP_DriveFDIcon      16 The floppy icon.
 * QStyle::SP_DriveHDIcon      17 The harddrive icon.
 * QStyle::SP_DriveCDIcon      18 The CD icon.
 * QStyle::SP_DriveDVDIcon      19 The DVD icon.
 * QStyle::SP_DriveNetIcon      20 The network icon.
 * QStyle::SP_DirHomeIcon      55 The home directory icon.
 * QStyle::SP_DirOpenIcon      21 The open directory icon.
 * QStyle::SP_DirClosedIcon     22 The closed directory icon.
 * QStyle::SP_DirIcon       37 The directory icon.
 * QStyle::SP_DirLinkIcon      23 The link to directory icon.
 * QStyle::SP_FileIcon       24 The file icon.
 * QStyle::SP_FileLinkIcon      25 The link to file icon.
 * QStyle::SP_QFileDialogStart     28 The "start" icon in a file dialog.
 * QStyle::SP_QFileDialogEnd     29 The "end" icon in a file dialog.
 * QStyle::SP_QFileDialogToParent    30 The "parent directory" icon in a file dialog.
 * QStyle::SP_QFileDialogNewFolder    31 The "create new folder" icon in a file dialog.
 * QStyle::SP_QFileDialogDetailedView   32 The detailed view icon in a file dialog.
 * QStyle::SP_QFileDialogInfoView    33 The file info icon in a file dialog.
 * QStyle::SP_QFileDialogContentsView   34 The contents view icon in a file dialog.
 * QStyle::SP_QFileDialogListView    35 The list view icon in a file dialog.
 * QStyle::SP_QFileDialogBack     36 The back arrow in a file dialog.
 * QStyle::SP_DockWidgetCloseButton    8 Close button on dock windows (see also QDockWidget).
 * QStyle::SP_ToolBarHorizontalExtensionButton 26 Extension button for horizontal toolbars.
 * QStyle::SP_ToolBarVerticalExtensionButton 27 Extension button for vertical toolbars.
 * QStyle::SP_DialogOkButton     38 Icon for a standard OK button in a QDialogButtonBox.
 * QStyle::SP_DialogCancelButton    39 Icon for a standard Cancel button in a QDialogButtonBox.
 * QStyle::SP_DialogHelpButton     40 Icon for a standard Help button in a QDialogButtonBox.
 * QStyle::SP_DialogOpenButton     41 Icon for a standard Open button in a QDialogButtonBox.
 * QStyle::SP_DialogSaveButton     42 Icon for a standard Save button in a QDialogButtonBox.
 * QStyle::SP_DialogCloseButton    43 Icon for a standard Close button in a QDialogButtonBox.
 * QStyle::SP_DialogApplyButton    44 Icon for a standard Apply button in a QDialogButtonBox.
 * QStyle::SP_DialogResetButton    45 Icon for a standard Reset button in a QDialogButtonBox.
 * QStyle::SP_DialogDiscardButton    46 Icon for a standard Discard button in a QDialogButtonBox.
 * QStyle::SP_DialogYesButton     47 Icon for a standard Yes button in a QDialogButtonBox.
 * QStyle::SP_DialogNoButton     48 Icon for a standard No button in a QDialogButtonBox.
 * QStyle::SP_ArrowUp       49 Icon arrow pointing up.
 * QStyle::SP_ArrowDown      50 Icon arrow pointing down.
 * QStyle::SP_ArrowLeft      51 Icon arrow pointing left.
 * QStyle::SP_ArrowRight      52 Icon arrow pointing right.
 * QStyle::SP_ArrowBack      53 Equivalent to SP_ArrowLeft when the current layout direction is Qt::LeftToRight, otherwise SP_ArrowRight.
 * QStyle::SP_ArrowForward      54 Equivalent to SP_ArrowRight when the current layout direction is Qt::LeftToRight, otherwise SP_ArrowLeft.
 * QStyle::SP_CommandLink      56 Icon used to indicate a Vista style command link glyph.
 * QStyle::SP_VistaShield      57 Icon used to indicate UAC prompts on Windows Vista. This will return a null pixmap or icon on all other platforms.
 * QStyle::SP_BrowserReload     58 Icon indicating that the current page should be reloaded.
 * QStyle::SP_BrowserStop      59 Icon indicating that the page loading should stop.
 * QStyle::SP_MediaPlay      60 Icon indicating that media should begin playback.
 * QStyle::SP_MediaStop      61 Icon indicating that media should stop playback.
 * QStyle::SP_MediaPause      62 Icon indicating that media should pause playback.
 * QStyle::SP_MediaSkipForward     63 Icon indicating that media should skip forward.
 * QStyle::SP_MediaSkipBackward    64 Icon indicating that media should skip backward.
 * QStyle::SP_MediaSeekForward     65 Icon indicating that media should seek forward.
 * QStyle::SP_MediaSeekBackward    66 Icon indicating that media should seek backward.
 * QStyle::SP_MediaVolume      67 Icon indicating a volume control.
 * QStyle::SP_MediaVolumeMuted     68 Icon indicating a muted volume control.
 */

//}}} --------------------------------------------------------------------------

void MainWindow::initMenu()
{
	QStyle * style = qApp->style();

	ui->actionOpen  ->setIcon (QIcon::fromTheme ("document-open"  ) )  ;
	ui->actionSaveAs  ->setIcon (QIcon::fromTheme ("document-save-as" ) )  ;
	ui->actionPrint->setIcon (QIcon::fromTheme ("printer"));
	//---
	ui->actionCopy  ->setIcon (QIcon::fromTheme ("edit-copy"   ) )  ;
	ui->actionCut   ->setIcon (QIcon::fromTheme ("edit-cut"   ) )  ;
	ui->actionPaste  ->setIcon (QIcon::fromTheme ("edit-paste"   ) )  ;
	ui->actionPreferences ->setIcon (QIcon::fromTheme ("preferences-desktop" ) )  ;
	//---
	ui->actionShowMessages->setIcon (QIcon::fromTheme ("mail-mark-read"  ) )  ;
	ui->actionConfigureFont->setIcon (QIcon::fromTheme ("fonts"));
	//---
	ui->actionQuit  ->setIcon (QIcon::fromTheme ("application-exit" ) )  ;
	ui->actionUndo  ->setIcon (QIcon::fromTheme ("edit-undo"   ) )  ;
	ui->actionRedo  ->setIcon (QIcon::fromTheme ("edit-redo"   ) )  ;

	ui->actionHelp  ->setIcon (style->standardIcon (QStyle::SP_DialogHelpButton)) ;
}

//}}} --------------------------------------------------------------------------
//{{{ .void initToolbar() ---------------------------------------------------

void MainWindow::initToolbar()
{
	m_toolBar = ui->mainToolBar;

	// creation du spacer
	QWidget * spacer = new QWidget (m_toolBar) ;
	spacer->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding) ;

	// création du bouton "save as" avec paramétrage intégré
	QToolButton* btnSaveAs = new QToolButton (m_toolBar);
	btnSaveAs->setPopupMode (QToolButton::MenuButtonPopup);
	QMenu* saveMenu = new QMenu (btnSaveAs);
	QActionGroup* group = new QActionGroup (saveMenu);
	foreach (const QString& format, m_config->supportedDocumentFormats ()) {
		QAction* action = new QAction (format, saveMenu);
		action->setCheckable (true);
		connect (action,
				 SIGNAL(toggled(bool)),
				 this,
				 SLOT(onFormatToogled(bool)));
		saveMenu->addAction (action);
		group->addAction (action);
		action->setChecked (m_config->optionSaveFormat () == format);
	}
	btnSaveAs->setMenu (saveMenu);
	btnSaveAs->setDefaultAction (ui->actionSaveAs);

	// remplissage de la toolbar
	m_toolBar->addAction (ui->actionOpen )  ;
	m_toolBar->addWidget (btnSaveAs);

	m_toolBar->addSeparator();

	m_toolBar->addAction (ui->actionPrint )  ;

	m_toolBar->addSeparator();

	m_toolBar->addAction (ui->actionPreferences) ;
	m_toolBar->addAction (ui->actionConfigureFont) ;

	m_toolBar->addSeparator();

	m_toolBar->addAction (ui->actionCopy )  ;
	m_toolBar->addAction (ui->actionCut )  ;
	m_toolBar->addAction (ui->actionPaste )  ;

	m_toolBar->addSeparator();

	m_toolBar->addAction (ui->actionUndo )  ;
	m_toolBar->addAction (ui->actionRedo )  ;

	m_toolBar->addSeparator();

	m_toolBar->addAction (ui->actionShowMessages) ;
	m_toolBar->addWidget(spacer);
	m_toolBar->addAction (ui->actionHelp);
	m_toolBar->addAction (ui->actionQuit )  ;
}
#include <QApplication>
//}}} --------------------------------------------------------------------------
//{{{ .void initConnect() ---------------------------------------------------

void MainWindow::initConnect()
{
	connect (m_edit,   SIGNAL(copyAvailable(bool)),   ui->actionCopy, SLOT(setEnabled(bool))     )  ;
	connect (m_edit,   SIGNAL(copyAvailable(bool)),   ui->actionCut, SLOT(setEnabled(bool))     )  ;
	connect (m_edit,   SIGNAL(undoAvailable(bool)),   ui->actionUndo, SLOT(setEnabled(bool))     )  ;
	connect (m_edit,   SIGNAL(redoAvailable(bool)),   ui->actionRedo, SLOT(setEnabled(bool))     )  ;

	connect (m_edit,
			 SIGNAL(documentIsEmpty(bool)),
			 this,
			 SLOT(onDocumentIsEmpty(bool)));

	connect (ui->actionPrint,
			 SIGNAL(triggered()),
			 this,
			 SLOT(onActionPrint()));

	connect (ui->actionCopy,		SIGNAL(triggered()),	m_edit,	SLOT(copy())        )  ;
	connect (ui->actionCut,		SIGNAL(triggered()),	m_edit,	SLOT(cut())        )  ;
	connect (ui->actionPaste,	SIGNAL(triggered()),	m_edit,	SLOT(paste())       )  ;
	connect (ui->actionUndo,		SIGNAL(triggered()),	m_edit,	SLOT(undo())        )  ;
	connect (ui->actionRedo,		SIGNAL(triggered()),	m_edit,	SLOT(redo())        )  ;

	connect (ui->actionQuit,
			 SIGNAL(triggered()),
			 this,
			 SLOT(onActionQuit ()));

	connect (ui->actionRunAutoSpelling,
			 SIGNAL(triggered()),
			 this,
			 SLOT(onActionRunAutoSpelling()));

	connect (ui->actionConfigureFont,
			 SIGNAL(triggered()),
			 this,
			 SLOT(onActionConfigureFont()));

//	connect	(m_progressDialog,
//			 SIGNAL(canceled()),
//			 m_ortho,
//			 SLOT(stopAutoSpelling()));

	connect	(m_edit,
			 SIGNAL(documentModified(bool)),
			 this,
			 SLOT(onDocumentModified(bool)));

	connect (m_edit,   SIGNAL(message(QString)),   this,   SLOT(onMessage(QString))     )  ;
}

//}}} --------------------------------------------------------------------------
//{{{ .void initDocument() --------------------------------------------------

void MainWindow::initDocument()
{
	m_edit = (TextEdit*) ui->edit;
	m_edit->setConfig (m_config);
}

//}}} --------------------------------------------------------------------------
//{{{ .void changeEvent (QEvent * e) ---------------------------------------

void MainWindow::changeEvent (QEvent * e)
{
	QMainWindow::changeEvent (e) ;
	switch (e->type())
	{
	case QEvent::LanguageChange :
		ui->retranslateUi (this) ;
		break;
	default:
		break;
	}
}

//}}} --------------------------------------------------------------------------
//{{{ .void on_actionPreferences_triggered() --------------------------------

void MainWindow::on_actionPreferences_triggered()
{
	// __ns__: replaced pointer by plain variable
	// why allocate ???

	Preferences pref (this) ;
	pref.exec();
	m_edit->forceUpdate ();
}

//}}} --------------------------------------------------------------------------
//{{{ .void on_actionShowMessages_triggered() -------------------------------

void MainWindow::on_actionShowMessages_triggered()
{
	ui->actionShowMessages->setIcon (QIcon::fromTheme ("mail-mark-read")) ;

	// __ns__: replaced pointer by plain variable
	// why allocate ???

	Messages msg (this) ;
	msg.setMessageList (m_messages) ;
	msg.exec();

	ui->actionShowMessages->setEnabled (! m_messages.isEmpty()) ;
}
//---------------------------------------------------------
void MainWindow::onActionPrint()
{
	QPrinter printer;
	QPrintDialog dial (&printer, this);
	dial.setWindowTitle (tr ("Imprimer le document"));
	if (dial.exec () == QDialog::Accepted) {
		m_edit->print (&printer);
	}
}

//}}} --------------------------------------------------------------------------
//{{{ .void onMessage (const QString & msg) --------------------------------

void MainWindow::onMessage (const QString & msg)
{
	m_messages << msg;
	ui->actionShowMessages->setIcon (QIcon::fromTheme ("mail-mark-unread")) ;
	ui->actionShowMessages->setEnabled (true) ;
}
//}}} --------------------------------------------------------------------------
//{{{ .void onActionConfigureFont() --------------------------------

void MainWindow::onActionConfigureFont()
{
	QFont currentFont (m_edit->font ());
	bool ok;
	QFont selectedFont (QFontDialog::getFont (&ok, currentFont, this, 0));
	if (ok) {
		m_edit->setFont (selectedFont);
		// sauvegarder préférence
		m_config->setOptionDefaultFont (selectedFont);
	}
}
//}}} --------------------------------------------------------------------------
//{{{ .void onActionRunAutoSpelling() --------------------------------

void MainWindow::onActionRunAutoSpelling()
{
//	m_edit->setPlainText (m_ortho->autoSpelling (m_edit->toPlainText ()));
}
//}}} --------------------------------------------------------------------------
//{{{ .void onOrthoAutoSpellingCount (int count) ---------------------------

void MainWindow::onOrthoAutoSpellingCount (int count)
{
	m_progressDialog->setValue (0);
	m_progressDialog->setMaximum (count);
}
//------------------------------------------------------
void MainWindow::onOrthoAutoSpellingAdvance (int advance)
{
	m_progressDialog->setValue (advance);
}

//}}} --------------------------------------------------------------------------
//{{{ .void on_actionOpen_triggered() ---------------------------------------

void MainWindow::on_actionOpen_triggered()
{
	QString path = QFileDialog::getOpenFileName (this, tr ("Ouvrir le document")) ;

	if (m_edit->open (path))
	{
		//		setWindowTitle (QString ("%1[*] - Dicodor").arg (path)) ;
		setWindowModified (false) ;
		setWindowFilePath (path) ;
	}
}

//}}} --------------------------------------------------------------------------
//{{{ .void on_actionSave_triggered () ---------------------------------------

void MainWindow::on_actionSaveAs_triggered ()
{
	if (m_edit->isEmpty ()) return;

	QString docPath = m_edit->documentTitle ();
	QFileInfo fi (docPath);

	QString fileName (QString ("%1%2.%3").arg(m_config->appExportPath ()).arg (fi.completeBaseName ()).arg (fi.suffix ()));

	QString saveFilePath = QFileDialog::getSaveFileName ( this,
														  tr ("Enregistrer le document"),
														  fileName,
														  QString (),
														  0,
														  QFileDialog::DontConfirmOverwrite);

	if (m_edit->saveAs (saveFilePath))
	{
		qDebug () << tr ("Sauvegarde correcte");
	}
	else
	{
		qDebug () << tr ("Erreur dans la sauvegarde");
	}
}

//}}} --------------------------------------------------------------------------
//{{{ .void onDocumentIsEmpty (bool b) ---------------------------------------

void MainWindow::onDocumentIsEmpty (bool b)
{
	ui->actionSaveAs->setDisabled (b);
	ui->actionPrint->setDisabled (b);
	ui->actionRunAutoSpelling->setDisabled (b);
}
//}}} --------------------------------------------------------------------------
//{{{ .void onDocumentModified ()

void MainWindow::onDocumentModified (bool m )
{
	setWindowModified (m);
}

//}}} --------------------------------------------------------------------------
//{{{ .void onFormatToogled (bool)

void MainWindow::onFormatToogled (bool)
{
	QAction* action = (QAction*) sender ();

	if (action != 0) m_config->setOptionSaveFormat (action->text ());
}

//}}} --------------------------------------------------------------------------
//{{{ .void on_actionHelp_triggered ()

void MainWindow::on_actionHelp_triggered ()
{
	About about;

	about.exec ();
}

//}}} ---------------------------------------
//{{{ .void onActionQuit ()

void MainWindow::onActionQuit ()
{
	int choice = QMessageBox::Discard;
	if (isWindowModified ())
	{
		choice = QMessageBox::warning (this,
									   tr ("Document modifié"),
									   tr("Le document a été modifié.\n"
										  "Voulez-vous l'enregistrer avant de quitter l'application ?"),
									   QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
									   QMessageBox::Save);
	}

	switch (choice)
	{
	case QMessageBox::Save:
		on_actionSaveAs_triggered ();
	case QMessageBox::Discard:
		close ();
	case QMessageBox::Cancel:
		break;
	}
}

//}}} --------------------------------------------------------------------------


